VPCフローログをAmazon Athenaで分析する
みなさん、こんにちは! AWS事業本部の青柳@福岡オフィスです。
今回は、VPCフローログ をS3に出力して、Amazon Athena で分析する方法についてご紹介します。
VPCフローログとは
VPC内のネットワークトラフィックをキャプチャ (捕捉) して、ログに保存する機能です。
フローログを設定できるリソース は以下の通りです:
- VPC
- サブネット
- ネットワークインターフェイス (ENI)
どのポイントに設定した場合でも、ネットワークトラフィックのキャプチャが行われるのは「ネットワークインターフェイス (ENI)」が対象となります。 (VPCやサブネットに対してフローログを設定した場合は、VPCやサブネット内に存在する全てのネットワークインターフェイスが対象になります)
ネットワークインターフェイスが対象ということは、EC2インスタンスやELB、RDSなどに出入りするパケットを可視化できるということですね。
フローログの出力先 に指定できるのは以下のサービスです:
- CloudWatch Logs
- S3バケット
ネットワークトラフィックの特定のアクセス傾向を検知してアラームを発する場合には、CloudWatch Logsへ出力します。
あるいは、今回のようにフローログを蓄積してAthenaで分析する場合にはS3バケットへ出力する、というように使い分けを行うのが良いでしょう。
設定方法
1. VPCフローログをS3へ出力するように設定する
AWSドキュメントの内容に沿って設定していきます。
Amazon S3 へのフローログの発行 - Amazon Virtual Private Cloud
まず、フローログの出力先となるS3バケットを作成しておきます。
準備ができましたら、フローログの設定を行います。 今回はVPCに対してフローログを設定します。
マネジメントコンソールで対象VPCの「フローログ」タブを選択して、「フローログの作成」をクリックします。
フローログの設定を入力します。
- フィルタ
- ・「承諾」: 通過を許可されたパケットのみ記録 ・「却下」: 通過を拒否されたパケットのみ記録 ・「すべて」: 「承諾」「却下」の両方のパケットを記録 今回は「すべて」を選択しました
- 送信先
- 「S3バケットへの送信」を選択します
- S3バケットARN
- 送信先S3バケットのARNを指定します (例:arn:aws:s3:::bucket_name)
- Log record format
- フローログに記録される項目について、デフォルトのままか、カスタマイズするのかを選択します
フローログに記録される各項目については、下記リンク先を参照してください。 フローログレコード
※ 2020年3月18日のアップデートで、VPCフローログに「タグ」が設定できるようになっています。 [アップデート] VPC Flow Logs にタグ付けできるようになりました | Developers.IO
なお、フローログの作成を行うと、保存先に指定したS3バケットに対して自動的に バケットポリシー が設定されます。 設定されるバケットポリシーの例:
{ "Version": "2012-10-17", "Id": "AWSLogDeliveryWrite20150319", "Statement": [ { "Sid": "AWSLogDeliveryWrite", "Effect": "Allow", "Principal": { "Service": "delivery.logs.amazonaws.com" }, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::cm-demo-vpc-flow-logs/AWSLogs/123456789012/*", "Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control" } } }, { "Sid": "AWSLogDeliveryAclCheck", "Effect": "Allow", "Principal": { "Service": "delivery.logs.amazonaws.com" }, "Action": "s3:GetBucketAcl", "Resource": "arn:aws:s3:::cm-demo-vpc-flow-logs" } ] }
サービス delivery.logs.amazonaws.com
に対して必要なアクセス権限が許可されていることが確認できます。
通常は自動で設定されたポリシーを変更する必要はありませんが、アカウントまたぎなど特殊なアクセス権限が必要な場合にはポリシーを修正してください。
2. S3バケットにフローログが記録されることを確認する
フローログを作成してしばらく経つと (数分~数十分)、S3バケット内にログが保存され始めます。
ログの保存先は、以下のようなフォルダ階層となっています。
{保存先バケット}/AWSLogs/{アカウントID}/vpcflowlogs/{リージョン名}/YYYY/MM/DD/
ログファイル名は以下の命名規則となります。
{アカウントID}_vpcflowlogs_{リージョン名}_{フローログID}_{タイムスタンプ}_{ハッシュ値}.log.gz
なお、ネットワークインターフェイスにトラフィックが発生しない限りはログが保存されません。 「いつまで経ってもログが記録されない!?」という場合には、VPC内でトラフィック対象のリソースが起動しているかどうか確認しましょう。
試しに、ログファイルをダウンロードして、アーカイブ (tar.gz形式) を解凍して、中身を見てみましょう。
version account-id interface-id srcaddr dstaddr srcport dstport protocol packets bytes start end action log-status 2 123456789012 eni-0c8d91464ef82783f 212.210.xx.xx 192.168.0.234 15056 22 6 1 40 1584474297 1584474304 REJECT OK 2 123456789012 eni-0c8d91464ef82783f 98.232.xx.xx 192.168.0.234 10313 22 6 1 40 1584474297 1584474304 REJECT OK 2 123456789012 eni-0c8d91464ef82783f 182.141.xx.xx 192.168.0.234 30373 22 6 1 40 1584474297 1584474304 REJECT OK 2 123456789012 eni-0c8d91464ef82783f 117.3.xx.xx 192.168.0.234 61166 23 6 1 44 1584474297 1584474304 REJECT OK 2 123456789012 eni-0c8d91464ef82783f 80.82.xx.xx 192.168.0.234 53225 4567 6 1 40 1584474312 1584474313 REJECT OK 2 123456789012 eni-0c8d91464ef82783f 198.108.xx.xx 192.168.0.234 20089 623 6 1 40 1584474334 1584474334 REJECT OK 2 123456789012 eni-0c8d91464ef82783f 98.14.xx.xx 192.168.0.234 43723 22 6 1 40 1584474357 1584474358 REJECT OK 2 123456789012 eni-0c8d91464ef82783f 209.17.xx.xx 192.168.0.234 59233 3000 6 1 44 1584474365 1584474376 REJECT OK ・・・
今回はVPC内にEC2インスタンスを1台起動して様子を見たのですが (もちろんセキュリティグループはちゃんと閉じています)、あっと言う間に見知らぬIPアドレスからSSH (22/TCP) のアクセスがあり、却下 (REJECT) されたことが記録されていました。
3. Athenaの外部テーブルを定義する
S3バケットに保存されたフローログをAthenaで分析できるようにします。
こちらも、AWSドキュメントの内容に沿って設定していきます。
Amazon VPC フローログのクエリ - Amazon Athena
AWSドキュメントの手順にはありませんが、テーブルを作成する前に「データベース」を作成しましょう。
マネジメントコンソールでAmazon Athenaの「クエリエディタ (Query Editor)」を開き、クエリ欄に以下の通り入力します。
CREATE DATABASE VPCFlowLogs;
「Run query」をクリックしてクエリを実行します。 Results欄に「Query successful.」と表示されれば正常にデータベースが作成されました。
左上の「Database」プルダウンから作成されたデータベースを選択します。
続いて、テーブルを作成するクエリを実行します。
S3バケットというAthenaの「外部」のデータソースを参照するため、外部テーブルを作成する CREATE EXTERNAL TABLE
文を用います。
CREATE EXTERNAL TABLE IF NOT EXISTS vpc_flow_logs ( version int, account string, interfaceid string, sourceaddress string, destinationaddress string, sourceport int, destinationport int, protocol int, numpackets int, numbytes bigint, starttime int, endtime int, action string, logstatus string ) PARTITIONED BY (dt string) ROW FORMAT DELIMITED FIELDS TERMINATED BY ' ' LOCATION 's3://cm-demo-vpc-flow-logs/AWSLogs/123456789012/vpcflowlogs/ap-northeast-1/' TBLPROPERTIES ("skip.header.line.count"="1");
テーブルの「列」は、フローログの作成時に指定した項目 (今回はデフォルトのまま) と1対1で対応するようにします。(列と項目の名前は一致している必要はありません)
PARTITIONED BY
句でテーブルに「パーティション分割」を指定します。
これは、ログデータの読み込み単位を日付単位で分割することにより、クエリ実行の速度向上や費用削減を図ることを目的としています。
(パーティション分割に関する詳細は後ほど説明します)
LOCATION
句にS3バケット内のフォルダへのパスを記述します。(日付部分である YYYY/MM/DD/
は含みません)
S3バケット名、アカウントID、リージョンは適宜書き換えてください。
「Run query」をクリックしてクエリを実行します。 Results欄に「Query successful.」と表示され、左側の「Table」欄に作成したテーブルが表示されていればOKです。
4. テーブルにパーティションを追加してデータを取り込む
この時点では、まだテーブルに実際のログデータは取り込まれていません。
テーブル作成時に「パーティション分割」を指定しましたが、具体的なパーティションを追加してあげることで対象のデータをテーブルにロードします。
具体的には以下のようなクエリを実行します。
ALTER TABLE vpc_flow_logs ADD PARTITION (dt='2020-03-17') location 's3://cm-demo-vpc-flow-logs/AWSLogs/123456789012/vpcflowlogs/ap-northeast-1/2020/03/17';
これは、S3バケットのパス ~/2020/03/17/
内のデータを、Athenaテーブルの dt='2020-03-17'
で指定されるパーティションに紐付けることを意味します。
(紐付けと同時にデータのロードが行われます)
「日付が変わるたびに上記のようなクエリを毎回実行するのは面倒だ」という場合は、「予め将来分のクエリをまとめて実行しておく」という方法もあります。
パーティションの追加は、まだ存在しないS3パスを指定して行うことが可能です。 例えば以下のシェルスクリプトは、向こう1年分のパーティションを追加するSQLクエリを生成します。
#!/bin/sh START_DATE=2020-04-01 END_DATE=2021-03-31 TABLE_NAME=vpc_flow_logs LOG_PATH=s3://cm-demo-vpc-flow-logs/AWSLogs/123456789012/vpcflowlogs/ap-northeast-1 CUR_DATE=$START_DATE echo "ALTER TABLE $TABLE_NAME ADD" while : do SUB_DIR=`date -d "$CUR_DATE" "+%Y/%m/%d"` echo -n "PARTITION (dt="\'"$CUR_DATE"\'") location "\'"$LOG_PATH/$SUB_DIR/"\' if [ $CUR_DATE = $END_DATE ]; then echo ";" break else echo fi CUR_DATE=`date -d "$CUR_DATE 1 day" "+%Y-%m-%d"` done
実行結果:
ALTER TABLE vpc_flow_logs ADD PARTITION (dt='2020-04-01') location 's3://cm-demo-vpc-flow-logs/AWSLogs/123456789012/vpcflowlogs/ap-northeast-1/2020/04/01/' PARTITION (dt='2020-04-02') location 's3://cm-demo-vpc-flow-logs/AWSLogs/123456789012/vpcflowlogs/ap-northeast-1/2020/04/02/' PARTITION (dt='2020-04-03') location 's3://cm-demo-vpc-flow-logs/AWSLogs/123456789012/vpcflowlogs/ap-northeast-1/2020/04/03/' PARTITION (dt='2020-04-04') location 's3://cm-demo-vpc-flow-logs/AWSLogs/123456789012/vpcflowlogs/ap-northeast-1/2020/04/04/' PARTITION (dt='2020-04-05') location 's3://cm-demo-vpc-flow-logs/AWSLogs/123456789012/vpcflowlogs/ap-northeast-1/2020/04/05/' ・・・ PARTITION (dt='2021-03-30') location 's3://cm-demo-vpc-flow-logs/AWSLogs/123456789012/vpcflowlogs/ap-northeast-1/2021/03/30/' PARTITION (dt='2021-03-31') location 's3://cm-demo-vpc-flow-logs/AWSLogs/123456789012/vpcflowlogs/ap-northeast-1/2021/03/31/';
一時的な調査などで特定日付のフローログをAthenaで分析したい場合は、日付単位でパーティションを追加すれば十分だと思います。
一方、恒常的にフローログのAthenaに取り込んで分析を行うような場合は、まとめてパーティションを追加しておくのが良いでしょう。
パーティション分割の詳細については、AWSドキュメントの以下ページを参照してください。 データのパーティション分割 - Amazon Athena
また、以下のページで ALTER TABLE ADD PARTITION
文、ALTER TABLE DROP PARTITION
文、SHOW PARTITIONS
文の構文を確認しておくと良いでしょう。
DDL ステートメント - Amazon Athena
5. ログデータに対してクエリを行う
これでログデータの分析を行う準備ができましたので、いくつか試してみましょう。
(例1) 期間を指定してログを抽出
クエリ:
SELECT from_unixtime(starttime, 9, 0) AS starttime_jst, from_unixtime(endtime, 9, 0) AS endtime_jst, interfaceid, sourceaddress, destinationaddress, sourceport, destinationport, protocol, numpackets, numbytes, action, logstatus FROM vpc_flow_logs WHERE from_unixtime(starttime, 9, 0) >= cast('2020-03-18 12:00:00 +09:00' as timestamp with time zone) AND from_unixtime(starttime, 9, 0) < cast('2020-03-18 13:00:00 +09:00' as timestamp with time zone) ORDER BY starttime;
実行結果:
starttime_jst endtime_jst interfaceid sourceaddress destinationaddress sourceport destinationport protocol numpackets numbytes action logstatus ------------------------------ ------------------------------ --------------------- ------------- ------------------ ---------- --------------- -------- ---------- -------- ------ --------- 2020-03-18 12:00:01.000 +09:00 2020-03-18 12:00:02.000 +09:00 eni-0c8d91464ef82783f 158.101.xx.xx 192.168.0.234 7070 22 6 1 40 REJECT OK 2020-03-18 12:00:01.000 +09:00 2020-03-18 12:00:02.000 +09:00 eni-0c8d91464ef82783f 182.231.xx.xx 192.168.0.234 3123 22 6 1 40 REJECT OK 2020-03-18 12:00:26.000 +09:00 2020-03-18 12:00:26.000 +09:00 eni-0c8d91464ef82783f 182.84.xx.xx 192.168.0.234 11873 22 6 1 40 REJECT OK 2020-03-18 12:00:40.000 +09:00 2020-03-18 12:00:47.000 +09:00 eni-0c8d91464ef82783f 158.214.xx.xx 192.168.0.234 62721 22 6 1 40 REJECT OK 2020-03-18 12:00:40.000 +09:00 2020-03-18 12:00:47.000 +09:00 eni-0c8d91464ef82783f 182.12.xx.xx 192.168.0.234 34105 22 6 1 40 REJECT OK 2020-03-18 12:00:40.000 +09:00 2020-03-18 12:00:47.000 +09:00 eni-0c8d91464ef82783f 158.21.xx.xx 192.168.0.234 8250 22 6 1 40 REJECT OK 2020-03-18 12:00:53.000 +09:00 2020-03-18 12:00:55.000 +09:00 eni-0c8d91464ef82783f 122.117.xx.xx 192.168.0.234 11676 23 6 1 40 REJECT OK 2020-03-18 12:00:53.000 +09:00 2020-03-18 12:00:55.000 +09:00 eni-0c8d91464ef82783f 201.218.xx.xx 192.168.0.234 50688 445 6 1 52 REJECT OK 2020-03-18 12:01:18.000 +09:00 2020-03-18 12:01:18.000 +09:00 eni-0c8d91464ef82783f 98.128.xx.xx 192.168.0.234 8353 22 6 1 40 REJECT OK 2020-03-18 12:01:26.000 +09:00 2020-03-18 12:01:26.000 +09:00 eni-0c8d91464ef82783f 209.141.xx.xx 192.168.0.234 48562 8088 6 1 44 REJECT OK ・・・ 2020-03-18 12:59:25.000 +09:00 2020-03-18 12:59:32.000 +09:00 eni-0c8d91464ef82783f 45.76.xx.xx 192.168.0.234 123 42753 17 1 76 ACCEPT OK 2020-03-18 12:59:25.000 +09:00 2020-03-18 12:59:32.000 +09:00 eni-0c8d91464ef82783f 192.168.0.234 45.76.xx.xx 42753 123 17 1 76 ACCEPT OK 2020-03-18 12:59:49.000 +09:00 2020-03-18 12:59:49.000 +09:00 eni-0c8d91464ef82783f 223.71.xx.xx 192.168.0.234 59286 1022 6 1 44 REJECT OK
(例2) 拒否されたパケットのアクセス元IPアドレスの上位10個
クエリ:
SELECT sourceaddress, COUNT(*) AS num_of_access FROM vpc_flow_logs WHERE action='REJECT' GROUP BY sourceaddress ORDER BY num_of_access DESC LIMIT 10;
実行結果:
sourceaddress num_of_access ------------- ------------- 195.231.xx.xx 193 209.141.xx.xx 113 104.244.xx.xx 103 185.156.xx.xx 48 195.54.xx.xx 44 185.156.xx.xx 42 92.63.xx.xx 41 83.97.xx.xx 38 185.156.xx.xx 37 92.118.xx.xx 35
おわりに
VPCフローログをS3バケットに出力する方法、S3バケットに保存されたフローログをAmazon Athenaを使って分析する方法についてご紹介しました。
セキュリティ問題やネットワークトラブルが発生した際など、大量に出力されるVPCフローログから必要な情報を得るために、VPCフローログのAthenaによる分析が有効だと思います。 必要が生じた時にスムーズにAthenaが使えるよう、実際に設定してみて確かめておくと良いのではないでしょうか。